/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | foam-extend: Open Source CFD
   \\    /   O peration     | Version:     4.1
    \\  /    A nd           | Web:         http://www.foam-extend.org
     \\/     M anipulation  | For copyright notice see file Copyright
-------------------------------------------------------------------------------
License
	This file is part of foam-extend.

	foam-extend is free software: you can redistribute it and/or modify it
	under the terms of the GNU General Public License as published by the
	Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	foam-extend is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.

Class
	Foam::cellMatcher

Description
	Base class for cellshape matchers (hexMatch, prismMatch, etc.). These are
	classes which given a mesh and cell number find out the orientation of
	the cellShape and construct cell-vertex to mesh-vertex mapping and
	cell-face to mesh-face mapping.

	For example,
	@verbatim
		hexMatcher hex(mesh);
		cellShape shape;
		..
		bool isHex = hex.match(cellI, shape);
	@endverbatim
	Now shape is set to the correct Hex cellShape (if @a isHex is true)

	Alternatively there is direct access to the vertex and face mapping:
	@verbatim
		const labelList& hexVertLabels = hex.vertLabels();
		const labelList& hexFaceLabels = hex.faceLabels();
	@endverbatim
	Now
	  - @c hexVertLabels[n] is vertex label of hex vertex n
	  - @c hexFaceLabels[n] is face   label of hex vertex n

	Process of cellShape recognition consists of following steps:
	- renumber vertices of cell to local vertex numbers
	- construct (local to cell) addressing edge-to-faces
	- construct (local to cell) addressing vertex and face to index in face
	- find most unique face shape (e.g. triangle for prism)
	- walk (following either vertices in face or jumping from face to other
	  face) to other faces and checking face sizes.
	- if nessecary try other rotations of this face
	  (only nessecary for wedge, tet-wedge)
	- if nessecary try other faces which most unique face shape
	  (never nessecary for hex degenerates)

	The whole calculation is done such that no lists are allocated during
	cell checking. E.g. localFaces_ are always sized to hold max. number
	of possible face vertices and a separate list is filled which holds
	the actusl face sizes.

	For now all hex-degenerates implemented. Numbering taken from picture in
	demoGuide.

SourceFiles
	cellMatcherI.H
	cellMatcher.C

\*---------------------------------------------------------------------------*/

#ifndef cellMatcher_H
#define cellMatcher_H

#include "labelList.H"
#include "faceList.H"
#include "boolList.H"
#include "Map.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam
{

// Forward declaration of classes
class primitiveMesh;
class cell;
class cellShape;
class cellModel;


class cellMatcher
{
protected:

	// Static functions

		//- Given start and end of edge generate unique key
		inline static label edgeKey
		(
			const label numVert,
			const label v0,
			const label v1
		);

		//- Step along face either in righthand or lefthand direction
		inline static label nextVert(const label, const label, const bool);

	// Protected data

		// Map from mesh to local vertex numbering
		Map<label> localPoint_;

		//- Faces using local vertex numbering
		faceList localFaces_;

		//- Number of vertices per face in localFaces_
		labelList faceSize_;

		//- Map from local to mesh vertex numbering
		labelList pointMap_;

		//- Map from local to mesh face numbering
		labelList faceMap_;

		//- Map from 'edge' to neighbouring faces
		labelList edgeFaces_;

		//- pointFaceIndex[localVertI][localFaceI] is index in localFace
		//  where localVertI is.
		labelListList pointFaceIndex_;

		//- After matching: holds mesh vertices in cellmodel order
		labelList vertLabels_;

		//- After matching: holds mesh faces in cellmodel order
		labelList faceLabels_;

		//- CellModel name
		const word cellModelName_;

		mutable const cellModel* cellModelPtr_;


	// Protected Member Functions

		//- Calculates localFaces. Returns number of local vertices (or -1
		//  if more than vertPerCell).
		label calcLocalFaces(const faceList& faces, const labelList& myFaces);

		//- Fill edge (start, end) to face number
		void calcEdgeAddressing(const label numVert);

		//- Fill vertex/face to index in face data structure
		void calcPointFaceIndex();

		//- Given start,end of edge lookup both faces sharing it and return
		//  face != localFaceI
		label otherFace
		(
			const label numVert,
			const label v0,
			const label v1,
			const label localFaceI
		) const;


private:

	// Private Member Functions

		//- Disallow default bitwise copy construct and assignment
		cellMatcher(const cellMatcher&);
		void operator=(const cellMatcher&);


public:

	// Static functions

		//- Create list with incrementing labels
		static labelList makeIdentity(const label nElems);


	// Constructors

		//- Construct given mesh and shape factors
		cellMatcher
		(
			const label vertPerCell,
			const label facePerCell,
			const label maxVertPerFace,
			const word& cellModelName
		);


	// Destructor

		virtual ~cellMatcher()
		{}


	// Member Functions

		// Access

			inline const Map<label>& localPoint() const;
			inline const faceList& localFaces() const;
			inline const labelList& faceSize() const;
			inline const labelList& pointMap() const;
			inline const labelList& faceMap() const;
			inline const labelList& edgeFaces() const;
			inline const labelListList& pointFaceIndex() const;
			inline const labelList& vertLabels() const;
			inline const labelList& faceLabels() const;
			inline const cellModel& model() const;


		// Write

			void write(Ostream& os) const;

		// Cell shape dependent

			virtual label nVertPerCell() const = 0;

			virtual label nFacePerCell() const = 0;

			virtual label nMaxVertPerFace() const = 0;

			//- Hash value of all face sizes of this shape. Can be used for
			//  quick initial recognition.
			virtual label faceHashValue() const = 0;

			//- Check whether number of face sizes match the shape.
			virtual bool faceSizeMatch(const faceList&, const labelList&)
				const = 0;

			//- Low level shape recognition. Return true if matches.
			//  Works in detection mode only (checkOnly=true) or in exact
			//  matching. Returns true and sets vertLabels_.
			//  Needs faces, faceOwner of all faces in 'mesh' and cell number
			//  and labels of faces for this cell.
			//  cellI only used in combination with faceOwner to detect owner
			//  status.
			virtual bool matchShape
			(
				const bool checkOnly,
				const faceList& faces,
				const labelList& faceOwner,
				const label cellI,
				const labelList& myFaces
			) = 0;

			//- Exact match. Uses faceSizeMatch.
			//  Returns true if cell matches shape exactly.
			virtual bool isA(const primitiveMesh& mesh, const label cellI) = 0;

			//- Exact match given all the faces forming a cell. No checks
			//  on whether faces match up and form a closed shape.
			virtual bool isA(const faceList&) = 0;

			//- Like isA but also constructs a cellShape (if shape matches)
			virtual bool matches
			(
				const primitiveMesh& mesh,
				const label cellI,
				cellShape& shape
			) = 0;

};


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

} // End namespace Foam

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#include "cellMatcherI.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#endif

// ************************************************************************* //
